import type { IntervalTaskProps } from '../../timer_manager'
import type { RequestConfig, RequestError } from './request_handler'
import { logger } from '../../../types/constants'
import { TimerManager } from '../../timer_manager'
import { ToolKit } from '../../utils/toolkit'

export interface RequestIntervalRecord {
  url: string
  lastRequestTime: number
  requestCount: number
  averageInterval: number
  lastResponse?: any
  lastError?: RequestError
}

export interface RequestIntervalConfig {
  /** 最小请求间隔（毫秒） */
  minInterval?: number
  /** 自动清理间隔 */
  cleanupInterval?: number
  /** 最大缓存大小 */
  maxCacheSize?: number
  /** 最大缓存时间（毫秒） */
  maxCacheTime?: number
}

export interface RequestIntervalCanResult {
  canRequest: boolean
  waitTime: number
  record?: RequestIntervalRecord
}

/**
 * 请求间隔管理器：防止重复请求，优化性能
 */
export class RequestInterval {
  private readonly name = 'RequestInterval'
  private static instance: RequestInterval
  private readonly timerManager: TimerManager = TimerManager.getInstance()
  private readonly DEFAULT_CONFIG: Required<RequestIntervalConfig> = {
    minInterval: 1000, // 默认1秒间隔
    cleanupInterval: 60 * 1000, // 每分钟清理一次
    maxCacheSize: 100, // 默认 100 条记录
    maxCacheTime: 5 * 60 * 1000, // 5分钟缓存
  }

  private readonly config: Required<RequestIntervalConfig> = this.DEFAULT_CONFIG
  private readonly intervalTask: IntervalTaskProps = {
    id: 'request-interval',
    interval: this.DEFAULT_CONFIG.cleanupInterval,
    running: false,
  }

  private records: Map<string, RequestIntervalRecord> = new Map()

  private constructor() {
    this.startCleanupTimer()
  }

  static getInstance(): RequestInterval {
    if (!RequestInterval.instance) {
      RequestInterval.instance = new RequestInterval()
    }
    return RequestInterval.instance
  }

  /**
   * 检查是否可以发起请求
   */
  canRequest(url: string): RequestIntervalCanResult {
    const normalizedUrl = ToolKit.browser.url.normalizeUrl(url)
    const record = this.records.get(normalizedUrl)
    const now = Date.now()

    if (!record)
      return { canRequest: true, waitTime: 0 }

    const timeSinceLastRequest = now - record.lastRequestTime
    const waitTime = Math.max(0, this.config.minInterval - timeSinceLastRequest)

    return {
      canRequest: waitTime <= 0,
      waitTime,
      record,
    }
  }

  /**
   * 记录请求开始
   */
  recordRequestStart(url: string, config: Pick<RequestConfig, 'enableCache' | 'maxCacheSize'>): void {
    const normalizedUrl = ToolKit.browser.url.normalizeUrl(url)
    const now = Date.now()
    const existingRecord = this.records.get(normalizedUrl)

    if (existingRecord) {
      // 更新现有记录
      const interval = now - existingRecord.lastRequestTime
      const totalIntervals = existingRecord.averageInterval * existingRecord.requestCount
      const newAverage = (totalIntervals + interval) / (existingRecord.requestCount + 1)

      existingRecord.lastRequestTime = now
      existingRecord.requestCount++
      existingRecord.averageInterval = newAverage
    }
    else {
      // 创建新记录
      this.records.set(normalizedUrl, {
        url: normalizedUrl,
        lastRequestTime: now,
        requestCount: 1,
        averageInterval: 0,
      })

      // 检查缓存大小限制
      if (this.records.size > (config.maxCacheSize || this.config.maxCacheSize))
        this.cleanupOldRecords()
    }
  }

  /**
   * 记录请求成功
   */
  recordRequestSuccess(url: string, config: Pick<RequestConfig, 'enableCache'>, response: any): void {
    if (!config.enableCache)
      return

    const normalizedUrl = ToolKit.browser.url.normalizeUrl(url)
    const record = this.records.get(normalizedUrl)

    if (record) {
      record.lastResponse = response
      record.lastError = undefined
    }
  }

  /**
   * 记录请求失败
   */
  recordRequestError(url: string, error: RequestError | undefined): void {
    const normalizedUrl = ToolKit.browser.url.normalizeUrl(url)
    const record = this.records.get(normalizedUrl)

    if (record)
      record.lastError = error
  }

  /**
   * 获取缓存的响应
   */
  getCachedResponse<T = any>(url: string, config: Pick<RequestConfig, 'enableCache'>): T | null {
    if (!config.enableCache)
      return null

    const normalizedUrl = ToolKit.browser.url.normalizeUrl(url)
    const record = this.records.get(normalizedUrl)

    if (!record || !record.lastResponse)
      return null

    // 检查缓存是否过期
    const now = Date.now()
    if (now - record.lastRequestTime > this.config.maxCacheTime) {
      record.lastResponse = undefined
      return null
    }

    return record.lastResponse as T
  }

  /**
   * 强制清除 URL 的记录
   */
  clearUrlRecord(url: string): boolean {
    const normalizedUrl = ToolKit.browser.url.normalizeUrl(url)
    return this.records.delete(normalizedUrl)
  }

  /**
   * 获取 URL 的统计信息
   */
  getUrlStats(url: string): RequestIntervalRecord | null {
    const normalizedUrl = ToolKit.browser.url.normalizeUrl(url)
    return this.records.get(normalizedUrl) || null
  }

  /**
   * 获取所有记录的统计信息
   */
  getAllStats(): Array<{ url: string, stats: RequestIntervalRecord }> {
    return Array.from(this.records.entries()).map(([url, stats]) => ({
      url,
      stats,
    }))
  }

  /**
   * 清理过期记录
   */
  private cleanupOldRecords(): void {
    const now = Date.now()
    const expiredUrls: string[] = []

    this.records.forEach((record, url) => {
      // 清理超过最大缓存时间的记录
      if (now - record.lastRequestTime > this.config.maxCacheTime * 2) {
        expiredUrls.push(url)
      }
    })

    expiredUrls.forEach(url => this.records.delete(url))

    if (expiredUrls.length > 0)
      logger.debug(`[${this.name}] 清理了 ${expiredUrls.length} 个过期记录`)
  }

  /**
   * 启动定时清理任务
   */
  private startCleanupTimer(): void {
    this.timerManager.createTimerTask({
      id: this.intervalTask.id,
      interval: this.intervalTask.interval,
      callback: () => {
        this.cleanupOldRecords()
      },
    })

    this.intervalTask.running = true
  }

  /**
   * 销毁管理器
   */
  destroy(): void {
    if (this.intervalTask.running) {
      this.timerManager.clearInterval(this.intervalTask.id)
      this.intervalTask.running = false
    }
    this.records.clear()
  }
}
